<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <p mv-text="msg"></p>
        <p mv-text="msg"></p>
        <p mv-text="msg"></p>
        <p mv-text="info"></p>
        <p mv-text="info"></p>
        <h1 mv-text="msg"></h1>
        <p mv-text="aaa"></p>
    </div>
</body>
<script>
    let Watcher=function(){};

    // 数据DOM数组设置
    // key 是需要操作的变量名称
    Watcher.prototype.setDom=function(rootDom,key){
        let sel = "[mv-text="+key+"]";
        this[key]=rootDom.querySelectorAll(sel);
    };

    // 变量更新，通知监控 完成对应DOM集合的更新
    Watcher.prototype.notify=function(key,nv){
        let tempArr=this[key];
        for (let i = 0; i < tempArr.length; i++) {
            tempArr[i].textContent=nv;
        }
    };

    // 实例创建完成是第一个更新页面操作
    Watcher.prototype.update=function(data){
        for (let key in data) {
            this.notify(key,data[key]);
        }
    };
    // 1.定义响应式对象构造器
    let Mvvm = function(options){
        // console.log(this instanceof Mvvm);
        if(!(this instanceof Mvvm)){
            console.warn('Mvvm is a constructor and should be called with the `new` keyword');
        }
        this.init(options);//开始初始化对象
    }
    // 对象的初始化
    Mvvm.prototype.init=function(options){
        //获取容器
        this.$el = document.querySelector(options.el);
        // 将数据仓库定义到vm上
        this._data = options.data;
        // 数据的劫持
        this.deps();
    }
    // 2.数据的劫持实现，通过循环数据仓库完成
    Mvvm.prototype.deps=function(){
        //为当前实例创建一个监控对象Watcher
        let watcher=new Watcher();
        this.temp=watcher;

        for(let key in this._data){
            //将容器里所有的包含key的Dom绑定在一起
            watcher.setDom(this.$el,key);
            // console.log(key);
            //以创建的this._data的仓库变量定义到对象的根属性上
            Object.defineProperty(this,key,{
                get(){
                    return this._data[key];
                },
                set(nv){
                    // console.log(nv);
                    this._data[key]=nv;
                    watcher.notify(key,nv);
                }
            });
        }
        watcher.update(this._data);
    }
    var vm=new Mvvm({
        el:"#app",
        data:{
            msg:"变量",
            info:"测试",
            aaa:"aaaaa"
        }
    });
</script>
</html>